/alu.c

 /*
 * Team Name: Focus
 * Team Members: Diana Groun, Edward Bassan
 * File Name; alu.c
 * Description: This file contains the methods that the alu operation needs.
 * Methods such as subtraction addition ect.
 */

#include "alu.h"
#include "global.h"
#include <stdlib.h>
#include <stdio.h>

/*
 * A AluPtr Constructor.
 */
AluPtr aluConstructor(void) {
        AluPtr alu = (AluPtr) malloc(sizeof(AluStr));
        alu->operandA = malloc(sizeof(Register));
        alu->operandB = malloc(sizeof(Register));
        alu->resultR = malloc(sizeof(Register));
        alu->modifier = 0;
        alu->negFlag = 0;
        alu->zeroFlag = 0;
        alu->posFlag = 0;
        alu->carryFlag = 0;
        alu->overflowFlag = 0;

        //Pointers to functions.
        alu->signOf = signOf;
        alu->xor = xor;
        alu->division = division;
        alu->multiplication = multiplication;
        alu->negation = negation;
        alu->addition = addition;
        alu->subtraction = subtraction;
        alu->and = and;
        alu->or = or;
        alu->not = not;
        alu->isUnary = isUnary;
        alu->getResult = getResult;
        alu->setFlags = setFlags;
        alu->displayAlu = displayAlu;
        alu->shiftLeft = shiftLeft;
        alu->shiftRight = shiftRight;
        return alu;
}
// Check the sign of the operand.
int signOf(AluPtr this, unsigned short operand)
{
    return ((operand & SIGN_MASK) ? 1 : 0);
}

/*
 * Shifts register value to left.
 * reg - the value to be shifted
 */
int shiftLeft(AluPtr this)
{
        this->resultR->value = this->operandA->value * 2;
        this->setFlags(this);
        return NO_ERROR;
}
/**
 * Shifts the register value to the right.
 * reg - the value to be shifted.
 */
int shiftRight(AluPtr this)
{
        this->resultR->value = this->operandA->value / 2;
        this->setFlags(this);
        return NO_ERROR;
}
/**
 * Subtract the operandB from operandA and sets flags.
 */
int subtraction(AluPtr this)
{
        this->resultR->value = this->operandA->value - this->operandB->value;
        this->setFlags(this);
        return NO_ERROR;
}
/**
 * Returns the result.
 */
unsigned short getResult(AluPtr this)
{
        return this->resultR->value;
}
/**
 * Negate a register value.
 */
int negation(AluPtr this)
{
        this->operandB->value = ~this->operandB->value;
        return NO_ERROR;
}
/**
 * And the operandA value with operandB
 */
int and(AluPtr this)
{
        this->resultR->value = this->operandA->value & this->operandB->value;
        return NO_ERROR;
}
/**
 * Not operandA value.
 */
int not(AluPtr this)
{
        return this->resultR->value = ~(this->operandA->value);
}
/**
 * Or operandA value with operandB value.
 */
int or(AluPtr this)
{
        this->resultR->value = this->operandA->value | this->operandB->value;
        return NO_ERROR;
}
/*
 * XOR operandA value with operandB value.
 */
int xor(AluPtr this)
{
        this->resultR->value = this->operandA->value ^ this->operandB->value;
        return NO_ERROR;
}
/**
 * Multiply the low order byte of operandA value with the low order byte of operandB value.
 */
int multiplication(AluPtr this)
{
        RegisterPtr a = newRegister();
        RegisterPtr b = newRegister();
        a->setRegister(a, this->operandA->value);
        b->setRegister(b, this->operandB->value);
        this->resultR->value = a->getLOB(a) * b->getLOB(b);
        return NO_ERROR;
}
/**
 * Divide operandA value with operandB value and save the remainder to register # 8.
 */
int division(AluPtr this,RegisterPtr remain)
{
        this->resultR->value = this->operandA->value / this->operandB->value;
        remain->value= this->operandA->value % this->operandB->value;

        return NO_ERROR;
}
/**
 * Add the operandA value with operandB value.
 */
int addition(AluPtr this)
{
        this->resultR->value = this->operandA->value + this->operandB->value;
        this->setFlags(this);
        return NO_ERROR;
}
/**
 * sets the flags for when the result is zero, positive, negative, carry and overflow.
 */
int setFlags(AluPtr this) {
        if (this->signOf(this, this->resultR->value)){
                this->negFlag = 1;
        }

        if (this->resultR->value == 0x00){
                this->zeroFlag = 0x1;
        }
        if (this->resultR->value < (this->operandA->value + this->operandB->value))
                this->carryFlag = 1;
        if (this->signOf(this, this->operandA->value == this->signOf(this, this->operandB->value))
                        && (this->signOf(this, this->operandA->value)) !=
                                        this->signOf(this, this->resultR->value))
           this->overflowFlag = 1;
        return NO_ERROR;
}
/**
 * NOT an operandA value.
 */
int isUnary(int modifier)
{
        return modifier == NOT;
}
/**
 * Display the values for operands,result and the flags.
 */
int displayAlu(AluPtr this)
{
        unsigned short A,B,R;
        A = this->operandA->value;
        B = this->operandB->value;
        R = this->resultR->value;
        printf("ALU.A: %.4X\n",A);
        printf("ALU.B: %.4X\n",B);
        printf("ALU.R: %.4X\n",R);
        printf("SW   : %X%X%X%X\n",this->negFlag,this->zeroFlag,this->carryFlag,
                        this->overflowFlag);
        return NO_ERROR;
}

/**
 * Test for the Alu.c
 */
/*
int main(void)
{
        AluPtr alu = aluConstructor();
        alu->operandA->value = 0x2;
        alu->operandB->value = 0x2;
        alu->aluOperation(alu, ADD);
        alu->displayAlu(alu);
        return 0;
}
*/
